package com.food.eat.search.service.impl;

import com.food.eat.search.pojo.ItemsES;
import com.food.eat.search.service.ItemElasticSearchService;
import com.food.eat.util.PagedGridResult;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author:RenPu
 * @Date: 2020/8/11 18:30
 * @Version: 1.0
 * @description:
 */


@Service
public class ItemElasticSearchImpl implements ItemElasticSearchService {


    @Resource
    private ElasticsearchTemplate esTemplate;


    /**
     * ElasticSearch实现全文检索，并且高亮展示
     *
     * @param keywords
     * @param sort
     * @param page
     * @param pageSize
     * @return
     */

    @Override
    public PagedGridResult searchItemsMessageInfo(String keywords, String sort, Integer page, Integer pageSize) {
        String preTag = "<font color='red'>";
        String postTag = "</font>";

        Pageable pageable = PageRequest.of(page, pageSize);


        //封装前端传来的字段实现，根据价格排序，销量排序，商品名称排序
        SortBuilder sortBuilder = null;
        if (sort.equals("c")) {
            sortBuilder = new FieldSortBuilder("sellCounts")
                    .order(SortOrder.DESC);
        } else if (sort.equals("p")) {
            sortBuilder = new FieldSortBuilder("price")
                    .order(SortOrder.ASC);
        } else {
            sortBuilder = new FieldSortBuilder("itemName.keyword")
                    .order(SortOrder.ASC);
        }

        String itemNameFiled = "itemName";

        /**
         * 封装前端输入的查询字符串，与es索引库的列进行匹配，实现高亮展示
         * 高亮的颜色目前在后端是固定的，为了便于灵活，可以注释掉使用es默认
         * 有前端来自定义高亮展示的颜色
         */

        SearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery(itemNameFiled, keywords))
                .withHighlightFields(new HighlightBuilder.Field(itemNameFiled)
                        .preTags(preTag)
                        .postTags(postTag)
                )
                .withSort(sortBuilder)
                .withPageable(pageable)
                .build();

        /**
         * 通过调用esTemplate的queryForPage方法，将封装好的query条件对象，以及索引库数据与实体类进行映射
         */
        AggregatedPage<ItemsES> pagedItems = esTemplate.queryForPage(query, ItemsES.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {


                /**
                 * response为从es索引库获取的数据响应结果
                 */
                List<ItemsES> itemHighLightList = new ArrayList<>();

                SearchHits hits = response.getHits();
                for (SearchHit h : hits) {
                    HighlightField highlightField = h.getHighlightFields().get(itemNameFiled);
                    String itemName = highlightField.getFragments()[0].toString();

                    String itemId = (String) h.getSourceAsMap().get("itemId");
                    String imgUrl = (String) h.getSourceAsMap().get("imgUrl");
                    Integer price = (Integer) h.getSourceAsMap().get("price");
                    Integer sellCounts = (Integer) h.getSourceAsMap().get("sellCounts");

                    ItemsES item = new ItemsES();
                    item.setItemId(itemId);
                    item.setItemName(itemName);
                    item.setImgUrl(imgUrl);
                    item.setPrice(price);
                    item.setSellCounts(sellCounts);

                    itemHighLightList.add(item);
                }

                return new AggregatedPageImpl<>((List<T>) itemHighLightList,
                        pageable,
                        response.getHits().totalHits);
            }
        });
//        System.out.println("检索后的总分页数目为：" + pagedStu.getTotalPages());
//        List<Stu> stuList = pagedStu.getContent();
//        for (Stu s : stuList) {
//            System.out.println(s);
//        }

        PagedGridResult gridResult = new PagedGridResult();
        gridResult.setRows(pagedItems.getContent());
        gridResult.setPage(page + 1);
        gridResult.setTotal(pagedItems.getTotalPages());
        gridResult.setRecords(pagedItems.getTotalElements());

        return gridResult;
    }

}
